#pragma once
/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Disk I/O Assistant Class
 *      Provides managed implementations of Win32 API Functions for hard-drive operations.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
#include "stdafx.h"
#include "FreeSpaceBlock.h"
#include "FreeSpaceBlockCollection.h"
#include "FileClusterMapEntry.h"
#include "FileClusterMapEntryCollection.h"

using namespace System;
using namespace System::Collections;
using namespace System::ComponentModel;
using namespace System::Runtime::InteropServices;
using namespace Microsoft::Win32::SafeHandles;

namespace Adaptive
{
	namespace Foundation
	{
		namespace IO
		{
			/// <summary>
			/// Provides managed implementations of Win32 API Functions for hard-drive operations.
			/// Provides wrappers for low-level Windows API calls.
			/// </summary>
			/// <remarks>
			/// This class provides methods for finding clusters and defragmenting 
			/// files on a disk.
			/// </remarks>
			public ref class DiskIoAssistant sealed
			{
			public:
				/*------------------------------------------------------------------------
				 * Public Static Methods / Functions
				 *----------------------------------------------------------------------*/
				#pragma region Public Static Methods / Functions
				/// <summary>
				/// Closes the supplied open handle.
				/// </summary>
				/// <param name="handle">
				/// An <see cref="IntPtr"/> containing the handle to be closed.
				/// </param>
				static void Close(IntPtr handle);
				/// <summary>
				/// Closes the supplied open handle.
				/// </summary>
				/// <param name="handle">
				/// A <see cref="SafeHandle"/> containing the handle to be closed.
				/// </param>
				static void Close(SafeHandle^ handle);
				/// <summary>
				/// Opens a handle to the specified device.
				/// </summary>
				/// <param name="deviceName">
				/// A logical drive name, such as "C:", or a physical item, such 
				/// as "PHYSICALDRIVE0", or a directory.
				/// </param>
				/// <returns>
				/// A valid file handle, if successful; otherwise, returns <b>null</b>.
				/// </returns>
				static SafeFileHandle^ OpenVolume(String^ deviceName);
				/// <summary>
				/// Opens a handle to the specified file.
				/// </summary>
				/// <param name="path">
				/// The path and name of the file to be opened.
				/// </param>
				/// <returns>
				/// An <see cref="SafeHandle"/> with the handle to the open file if 
				/// successful; otherwise, returns <b>null</b>.
				/// </returns>
				static SafeFileHandle^ OpenFile(String^ path);
				/// <summary>
				/// Gets the cluster size on the specified drive.
				/// </summary>
				/// <param name="driveLetter">A character value specifying the drive letter.</param>
				/// <returns>
				/// The number of bytes contained in a single cluster.
				/// </returns>
				static __int64 GetDriveClusterSize(Char driveLetter);
				/// <summary>
				/// Gets the cluster size on the specified drive.
				/// </summary>
				/// <param name="driveLetter">A string specifying the drive letter.</param>
				/// <returns>
				/// The number of bytes contained in a single cluster.
				/// </returns>
				static __int64 GetDriveClusterSize(String^ driveLetter);
				/// <summary>
				/// Gets the size of the specified file, in bytes.
				/// </summary>
				/// <param name="fileName"></param>
				/// <returns>
				/// The size of the specified file, in bytes, or zero (0) if the file is not present.
				/// </returns>
				static __int64 GetFileSizeInBytes(String^ fileName);
				/// <summary>
				/// Gets the cluster map for the specified file.
				/// </summary>
				/// <param name="fileName">The name of the file for which a map is to be retrieved.</param>
				/// <returns>
				/// A <see cref="FileClusterMapEntryCollection"/> instance containing the entries for each
				/// fragmented cluster map entry.  An unfragmented file will have one (1) entry in the result.
				/// </returns>
				static FileClusterMapEntryCollection^ GetFileLocationData(String^ fileName);
				/// <summary>
				/// Gets the size of memory required to contain the unmanaged FILEMAP entries for the 
				/// specified file.
				/// </summary>
				/// <param name="fileName">The name of the file for which a map is to be retrieved.</param>
				/// <returns>
				/// This returns the size of the buffer required for an <b>unmanaged</b> FILEMAP array to 
				/// contain the neccessary entries for the file cluster map.
				/// </returns>
				static __int64 GetFileLocationDataSize(String^ fileName);
				/// <summary>
				/// Locates the first cluster position on the specified drive where the number of
				/// contiguous unused bytes are present.
				/// </summary>
				/// <param name="driveLetter">A character value specifying the drive letter.</param>
				/// <returns>
				/// The logical cluster number on the drive of the first free space location of the 
				/// specified size.
				/// </returns>
				static __int64 GetFirstFreeSpace(Char driveLetter, __int64 bytesRequired);
				/// <summary>
				/// Locates the first cluster position on the specified drive where the number of
				/// contiguous unused bytes are present.
				/// </summary>
				/// <param name="driveLetter">A string specifying the drive letter.</param>
				/// <returns>
				/// The logical cluster number on the drive of the first free space location of the 
				/// specified size.
				/// </returns>
				static __int64 GetFirstFreeSpace(String^ driveLetter, __int64 bytesRequired);
				/// <summary>
				/// Locates the last cluster position on the specified drive where the number of
				/// contiguous unused bytes are present.
				/// </summary>
				/// <param name="driveLetter">A character value specifying the drive letter.</param>
				/// <returns>
				/// The logical cluster number on the drive of the last free space location of the 
				/// specified size.
				/// </returns>
				static __int64 GetLastFreeSpace(Char driveLetter, __int64 bytesRequired);
				/// <summary>
				/// Locates the last cluster position on the specified drive where the number of
				/// contiguous unused bytes are present.
				/// </summary>
				/// <param name="driveLetter">A string specifying the drive letter.</param>
				/// <returns>
				/// The logical cluster number on the drive of the last free space location of the 
				/// specified size.
				/// </returns>
				static __int64 GetLastFreeSpace(String^ driveLetter, __int64 bytesRequired);
				/// <summary>
				/// Gets the size of the volume bitmap, in bytes.
				/// </summary>
				/// <param name="driveLetter">A character value specifying the drive letter.</param>
				/// <returns>
				/// The number of bytes required to contain the volume bitmap.
				/// </returns>
				static int GetVolumeBitmapSize(Char driveLetter);
				/// <summary>
				/// Gets the size of the volume bitmap, in bytes.
				/// </summary>
				/// <param name="driveLetter">A string specifying the drive letter.</param>
				/// <returns>
				/// The number of bytes required to contain the volume bitmap.
				/// </returns>
				static int GetVolumeBitmapSize(String^ driveLetter);
				/// <summary>
				/// Gets the volume bitmap as a byte array.
				/// </summary>
				/// <param name="driveLetter">A character value specifying the drive letter.</param>
				/// <returns>
				/// An array of bytes representing the cluster usage statistics for the specified drive.
				/// </returns>
				static array<Byte>^ GetVolumeBitmap(Char driveLetter);
				/// <summary>
				/// Gets the volume bitmap as a byte array.
				/// </summary>
				/// <param name="driveLetter">A string specifying the drive letter.</param>
				/// <returns>
				/// An array of bytes representing the cluster usage statistics for the specified drive.
				/// </returns>
				static array<Byte>^ GetVolumeBitmap(String^ driveLetter);
				/// <summary>
				/// Gets the volume cluster usage bitmap.
				/// </summary>
				/// <param name="deviceName">
				/// A logical drive name, such as "C:", or a physical item, such 
				/// as "PHYSICALDRIVE0", or a directory.
				/// </param>
				/// <returns>A <see cref="BitArray"/> containing a boolean value for each cluster.</returns>
				static BitArray^ GetVolumeMap(String^ deviceName);
				/// <summary>
				/// Moves a virtual cluster for a file to a logical cluster on disk for the number of specified clusters.
				/// </summary>
				/// <param name="deviceName">
				/// A logical drive name, such as "C:", or a physical item, such 
				/// as "PHYSICALDRIVE0", or a directory.
				/// </param>
				/// <param name="path">The path and name of the file to be moved.</param>
				/// <param name="numberOfClusterToBeMoved">The cluster number in file to move</param>
				/// <param name="diskClusterToMoveTo">The cluster on disk to move to</param>
				/// <param name="numberOfClustersToMove">The number of clusters to be moved.</param>
				static void MoveFile(String^ deviceName, String^ path,
											__int64 numberOfClusterToBeMoved,
											__int64 diskClusterToMoveTo,
											int numberOfClustersToMove);
				/// <summary>
				/// Attempts to move the specified file to the first open space on the drive with enough
				/// contiguous free space to contain the file.
				/// </summary>
				/// <remarks>
				/// This function may or may not succeed, based on the system's behavior.
				/// </remarks>
				/// <param name="fileName">The name of the file to be moved.</param>
				void MoveFileToFirstFreeSpace(String^ fileName);
				/// <summary>
				/// Attempts to move the specified file to the last open space at the end of the drive with enough
				/// contiguous free space to contain the file.
				/// </summary>
				/// <remarks>
				/// This function may or may not succeed, based on the system's behavior.
				/// </remarks>
				/// <param name="fileName">The name of the file to be moved.</param>
				void MoveFileToLastFreeSpace(String^ fileName);
				/// <summary>
				/// Moves a single file cluster to the specified position.
				/// </summary>
				/// <remarks>
				/// This function may or may not succeed, based on system behavior.  The function may return 
				/// <b>true</b> even if the system does not actually perform the specified task.
				/// </remarks>
				/// <param name="volumeHandle">An <see cref="IntPtr"/> containing the handle to the open volume.</param>
				/// <param name="fileHandle">An <see cref="IntPtr"/> containing the handle to the open file.</param>
				/// <param name="logicalClusterNumber">The new logical position to which the cluster is to be moved.</param>
				/// <param name="virtualClusterNumber">The file-position-relative virtual cluster number of the cluster to be moved.</param>
				/// <returns>
				/// <b>true</b> if the operation completes successfully; otherwise, returns <b>false</b>.
				/// </returns>
				bool MoveSingleCluster(IntPtr volumeHandle, IntPtr fileHandle, __int64 logicalClusterNumber, 
												__int64 virtualClusterNumber);
				/// <summary>
				/// Moves a single file cluster to the specified position.
				/// </summary>
				/// <remarks>
				/// This function may or may not succeed, based on system behavior.  The function may return 
				/// <b>true</b> even if the system does not actually perform the specified task.
				/// </remarks>
				/// <param name="volumeHandle">An <see cref="SafeFileHandle"/> containing the handle to the open volume.</param>
				/// <param name="fileHandle">An <see cref="SafeFileHandle"/> containing the handle to the open file.</param>
				/// <param name="logicalClusterNumber">The new logical position to which the cluster is to be moved.</param>
				/// <param name="virtualClusterNumber">The file-position-relative virtual cluster number of the cluster to be moved.</param>
				/// <returns>
				/// <b>true</b> if the operation completes successfully; otherwise, returns <b>false</b>.
				/// </returns>
				bool MoveSingleCluster(SafeFileHandle^ volumeHandle, SafeFileHandle^ fileHandle, __int64 logicalClusterNumber, 
												__int64 virtualClusterNumber);
				/// <summary>
				/// Finds last large block of free space on the drive.
				/// </summary>
				/// <param name="drive">The drive to be checked.</param>
				/// <returns>
				/// The number of the cluster at which the block begins.
				/// </returns>
				static int FindLastOpenBlockStart(String^ drive);
				/// <summary>
				/// Gets the list of free space blocks on the specified drive.
				/// </summary>
				/// <param name="deviceName">
				/// A logical drive name, such as "C:", or a physical item, such 
				/// as "PHYSICALDRIVE0", or a directory.
				/// </param>
				/// <returns>
				/// A <see cref="FreeSpaceBlockCollection"/> instance containing the definitions for each
				/// free space block.
				/// </returns>
				static FreeSpaceBlockCollection^ GetFreeSpaceBlocks(String^  deviceName);
				#pragma endregion

				private:
					DiskIoAssistant();
			};
		}
	}
}